
package org.linlinjava.litemall.wx.service;

import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.linlinjava.litemall.core.express.ExpressService;
import org.linlinjava.litemall.core.express.dao.ExpressInfo;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.qcode.QCodeService;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.core.util.IpUtil;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallAddress;
import org.linlinjava.litemall.db.domain.LitemallCart;
import org.linlinjava.litemall.db.domain.LitemallComment;
import org.linlinjava.litemall.db.domain.LitemallCoupon;
import org.linlinjava.litemall.db.domain.LitemallCouponUser;
import org.linlinjava.litemall.db.domain.LitemallGoodsProduct;
import org.linlinjava.litemall.db.domain.LitemallGroupon;
import org.linlinjava.litemall.db.domain.LitemallGrouponRules;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
import org.linlinjava.litemall.db.domain.LitemallUser;
import org.linlinjava.litemall.db.domain.LitemallUserFormid;
import org.linlinjava.litemall.db.service.CouponVerifyService;
import org.linlinjava.litemall.db.service.LitemallAddressService;
import org.linlinjava.litemall.db.service.LitemallCartService;
import org.linlinjava.litemall.db.service.LitemallCommentService;
import org.linlinjava.litemall.db.service.LitemallCouponUserService;
import org.linlinjava.litemall.db.service.LitemallGoodsProductService;
import org.linlinjava.litemall.db.service.LitemallGrouponRulesService;
import org.linlinjava.litemall.db.service.LitemallGrouponService;
import org.linlinjava.litemall.db.service.LitemallOrderGoodsService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.db.service.LitemallUserFormIdService;
import org.linlinjava.litemall.db.service.LitemallUserService;
import org.linlinjava.litemall.db.util.CouponUserConstant;
import org.linlinjava.litemall.db.util.OrderHandleOption;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.AUTH_OPENID_UNACCESS;
import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.GROUPON_EXPIRED;
import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.ORDER_COMMENTED;
import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.ORDER_COMMENT_EXPIRED;
import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.ORDER_INVALID;
import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.ORDER_INVALID_OPERATION;
import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.ORDER_PAY_FAIL;
import static org.linlinjava.litemall.wx.model.wxpay.WxResponseCode.ORDER_UNKNOWN;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单服务
 *
 * <p>
 * 订单状态：
 * 101 订单生成，未支付；
 * 102，下单后未支付用户取消；
 * 103，下单后未支付超时系统自动取消
 * 201 支付完成，商家未发货；
 * 202，订单生产，已付款未发货，但是退款取消；
 * 301 商家发货，用户未确认；
 * 401 用户确认收货；
 * 402 用户没有确认收货超过一定时间，系统自动确认收货；
 *
 * <p>
 * 用户操作：
 * 当101用户未付款时，此时用户可以进行的操作是取消订单，或者付款操作
 * 当201支付完成而商家未发货时，此时用户可以取消订单并申请退款
 * 当301商家已发货时，此时用户可以有确认收货的操作
 * 当401用户确认收货以后，此时用户可以进行的操作是删除订单，评价商品，或者再次购买
 * 当402系统自动确认收货以后，此时用户可以删除订单，评价商品，或者再次购买
 *
 * <p>
 * 注意：目前不支持订单退货和售后服务
 */
@Service
public class WxOrderService {

	private final Log logger = LogFactory.getLog(WxOrderService.class);

	@Autowired
	private LitemallUserService userService;

	@Autowired
	private LitemallOrderService orderService;

	@Autowired
	private LitemallOrderGoodsService orderGoodsService;

	@Autowired
	private LitemallAddressService addressService;

	@Autowired
	private LitemallCartService cartService;

	@Autowired
	private LitemallGoodsProductService productService;

	@Autowired
	private WxPayService wxPayService;

	@Autowired
	private NotifyService notifyService;

	@Autowired
	private LitemallUserFormIdService formIdService;

	@Autowired
	private LitemallGrouponRulesService grouponRulesService;

	@Autowired
	private LitemallGrouponService grouponService;

	@Autowired
	private QCodeService qCodeService;

	@Autowired
	private ExpressService expressService;

	@Autowired
	private LitemallCommentService commentService;

	@Autowired
	private LitemallCouponUserService couponUserService;

	@Autowired
	private CouponVerifyService couponVerifyService;

	/**
	 * 订单列表
	 *
	 * @param userId   用户ID
	 * @param showType 订单信息：
	 *                 0，全部订单；
	 *                 1，待付款；
	 *                 2，待发货；
	 *                 3，待收货；
	 *                 4，待评价。
	 * @param page     分页页数
	 * @param limit    分页大小
	 * @return 订单列表
	 */
	public Object list(Integer userId, Integer showType, Integer page, Integer limit, String sort, String order) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		List<Short> orderStatus = OrderUtil.orderStatus(showType);
		List<LitemallOrder> orderList = orderService.queryByOrderStatus(userId, orderStatus, page, limit, sort, order);		
		List<Map<String, Object>> orderVoList = new ArrayList<>(orderList.size());
		for (LitemallOrder o : orderList) {
			Map<String, Object> orderVo = new HashMap<>();
			orderVo.put("id", o.getId());
			orderVo.put("orderSn", o.getOrderSn());
			orderVo.put("actualPrice", o.getActualPrice());
			orderVo.put("orderStatusText", OrderUtil.orderStatusText(o));
			orderVo.put("handleOption", OrderUtil.build(o));
			LitemallGroupon groupon = grouponService.queryByOrderId(o.getId());
			if (groupon != null) {
			    orderVo.put("isGroupin", true);
			} else {
			    orderVo.put("isGroupin", false);
			}
			List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(o.getId());
			List<Map<String, Object>> orderGoodsVoList = new ArrayList<>(orderGoodsList.size());
			for (LitemallOrderGoods orderGoods : orderGoodsList) {
				Map<String, Object> orderGoodsVo = new HashMap<>();
				orderGoodsVo.put("id", orderGoods.getId());
				orderGoodsVo.put("goodsName", orderGoods.getGoodsName());
				orderGoodsVo.put("number", orderGoods.getNumber());
				orderGoodsVo.put("picUrl", orderGoods.getPicUrl());
				orderGoodsVo.put("specifications", orderGoods.getSpecifications());
				orderGoodsVoList.add(orderGoodsVo);
			}
			orderVo.put("goodsList", orderGoodsVoList);
			orderVoList.add(orderVo);
		}
		return ResponseUtil.okList(orderVoList, orderList);
	}

	/**
	 * 订单详情
	 *
	 * @param userId  用户ID
	 * @param orderId 订单ID
	 * @return 订单详情
	 */
	public Object detail(Integer userId, Integer orderId) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		// 订单信息
		LitemallOrder order = orderService.findById(orderId);
		if (null == order) {
			return ResponseUtil.fail(ORDER_UNKNOWN, "订单不存在");
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.fail(ORDER_INVALID, "不是当前用户的订单");
		}
		Map<String, Object> orderVo = new HashMap<String, Object>();
		orderVo.put("id", order.getId());
		orderVo.put("orderSn", order.getOrderSn());
		orderVo.put("addTime", order.getAddTime());
		orderVo.put("consignee", order.getConsignee());
		orderVo.put("mobile", order.getMobile());
		orderVo.put("address", order.getAddress());
		orderVo.put("goodsPrice", order.getGoodsPrice());
		orderVo.put("couponPrice", order.getCouponPrice());
		orderVo.put("freightPrice", order.getFreightPrice());
		orderVo.put("actualPrice", order.getActualPrice());
		orderVo.put("orderStatusText", OrderUtil.orderStatusText(order));
		orderVo.put("handleOption", OrderUtil.build(order));
		orderVo.put("expCode", order.getShipChannel());
		orderVo.put("expNo", order.getShipSn());
		List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
		Map<String, Object> result = new HashMap<>();
		result.put("orderInfo", orderVo);
		result.put("orderGoods", orderGoodsList);
		// 订单状态为已发货且物流信息不为空
		// "YTO", "800669400640887922"
		if (order.getOrderStatus().equals(OrderUtil.STATUS_SHIP)) {
			ExpressInfo ei = expressService.getExpressInfo(order.getShipChannel(), order.getShipSn());
			result.put("expressInfo", ei);
		}
		return ResponseUtil.ok(result);	
	}

	/**
	 * 提交订单
	 * <p>
	 * 1. 创建订单表项和订单商品表项;
	 * 2. 购物车清空;
	 * 3. 优惠券设置已用;
	 * 4. 商品货品库存减少;
	 * 5. 如果是团购商品，则创建团购活动表项。
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{cartId：xxx, addressId: xxx, couponId: xxx, message: xxx, grouponRulesId: xxx, grouponLinkId: xxx}
	 * @return 提交订单操作结果
	 */
	@Transactional
	public Object submit(Integer userId, String body) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		if (body == null) {
			return ResponseUtil.badArgument();
		}
		Integer cartId = JacksonUtil.parseInteger(body, "cartId");
		Integer addressId = JacksonUtil.parseInteger(body, "addressId");
		Integer couponId = JacksonUtil.parseInteger(body, "couponId");
		String message = JacksonUtil.parseString(body, "message");
		Integer grouponRulesId = JacksonUtil.parseInteger(body, "grouponRulesId");
		Integer grouponLinkId = JacksonUtil.parseInteger(body, "grouponLinkId");
		// 如果是团购项目, 验证活动是否有效
		if (grouponRulesId != null && grouponRulesId > 0) {
			LitemallGrouponRules rules = grouponRulesService.queryById(grouponRulesId);
			// 找不到记录
			if (rules == null) {
				return ResponseUtil.badArgument();
			}
			// 团购活动已经过期
			if (grouponRulesService.isExpired(rules)) {
				return ResponseUtil.fail(GROUPON_EXPIRED, "团购活动已过期!");
			}
		}
		if (cartId == null || addressId == null || couponId == null) {
			return ResponseUtil.badArgument();
		}
		// 收货地址
		LitemallAddress checkedAddress = addressService.query(userId, addressId);
		if (checkedAddress == null) {
			return ResponseUtil.badArgument();
		}
		// 团购优惠
		BigDecimal grouponPrice = new BigDecimal(0.00);
		LitemallGrouponRules grouponRules = grouponRulesService.queryById(grouponRulesId);
		if (grouponRules != null) {
			grouponPrice = grouponRules.getDiscount();
		}
		// 货品价格
		List<LitemallCart> checkedGoodsList = null;
		if (cartId.equals(0)) {
			checkedGoodsList = cartService.queryByUidAndChecked(userId);
		} else {
			LitemallCart cart = cartService.findById(cartId);
			checkedGoodsList = new ArrayList<>(1);
			checkedGoodsList.add(cart);
		}
		if (checkedGoodsList.size() == 0) {
			return ResponseUtil.badArgumentValue();
		}
		BigDecimal checkedGoodsPrice = new BigDecimal(0.00);
		for (LitemallCart checkGoods : checkedGoodsList) {
			// 只有当团购规格商品ID符合才进行团购优惠
			if (grouponRules != null && grouponRules.getGoodsId().equals(checkGoods.getGoodsId())) {
				checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice()
					.subtract(grouponPrice)
					.multiply(new BigDecimal(checkGoods.getNumber())));
			} else {
				checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice()
					.multiply(new BigDecimal(checkGoods.getNumber())));
			}
		}
		// 获取可用的优惠券信息
		// 使用优惠券减免的金额
		BigDecimal couponPrice = new BigDecimal(0.00);
		// 如果couponId=0则没有优惠券，couponId=-1则不使用优惠券
		if (couponId != 0 && couponId != -1) {
			LitemallCoupon coupon = couponVerifyService.checkCoupon(userId, couponId, checkedGoodsPrice);
			if (coupon == null) {
				return ResponseUtil.badArgumentValue();
			}
			couponPrice = coupon.getDiscount();
		}
		// 根据订单商品总价计算运费，满足条件（例如88元）则免运费，否则需要支付运费（例如8元）；
		BigDecimal freightPrice = new BigDecimal(0.00);
		if (checkedGoodsPrice.compareTo(SystemConfig.getFreightLimit()) < 0) {
			freightPrice = SystemConfig.getFreight();
		}
		// 可以使用的其他钱，例如用户积分
		BigDecimal integralPrice = new BigDecimal(0.00);	
		// 订单费用
		BigDecimal orderTotalPrice = checkedGoodsPrice.add(freightPrice)
			.subtract(couponPrice)
			.max(new BigDecimal(0.00));
		// 最终支付费用
		BigDecimal actualPrice = orderTotalPrice.subtract(integralPrice);
		Integer orderId = null;
		LitemallOrder order = null;
		// 订单
		order = new LitemallOrder();
		order.setUserId(userId);
		order.setOrderSn(orderService.generateOrderSn(userId));
		order.setOrderStatus(OrderUtil.STATUS_CREATE);
		order.setConsignee(checkedAddress.getName());
		order.setMobile(checkedAddress.getTel());
		order.setMessage(message);
		String detailedAddress = checkedAddress.getProvince() + 
			checkedAddress.getCity() + checkedAddress.getCounty() + " " + checkedAddress.getAddressDetail();
		order.setAddress(detailedAddress);
		order.setGoodsPrice(checkedGoodsPrice);
		order.setFreightPrice(freightPrice);
		order.setCouponPrice(couponPrice);
		order.setIntegralPrice(integralPrice);
		order.setOrderPrice(orderTotalPrice);
		order.setActualPrice(actualPrice);
		// 有团购活动
		if (grouponRules != null) {
			// 团购价格
			order.setGrouponPrice(grouponPrice);
		} else {
			// 团购价格
			order.setGrouponPrice(new BigDecimal(0.00));
		}
		// 添加订单表项
		orderService.add(order);
		orderId = order.getId();
		// 添加订单商品表项
		for (LitemallCart cartGoods : checkedGoodsList) {
			// 订单商品
			LitemallOrderGoods orderGoods = new LitemallOrderGoods();
			orderGoods.setOrderId(order.getId());
			orderGoods.setGoodsId(cartGoods.getGoodsId());
			orderGoods.setGoodsSn(cartGoods.getGoodsSn());
			orderGoods.setProductId(cartGoods.getProductId());
			orderGoods.setGoodsName(cartGoods.getGoodsName());
			orderGoods.setPicUrl(cartGoods.getPicUrl());
			orderGoods.setPrice(cartGoods.getPrice());
			orderGoods.setNumber(cartGoods.getNumber());
			orderGoods.setSpecifications(cartGoods.getSpecifications());
			orderGoods.setAddTime(LocalDateTime.now());
			orderGoodsService.add(orderGoods);
		}
		// 删除购物车里面的商品信息
		cartService.clearGoods(userId);
		// 商品货品数量减少
		for (LitemallCart checkGoods : checkedGoodsList) {
			Integer productId = checkGoods.getProductId();
			LitemallGoodsProduct product = productService.findById(productId);
			Integer remainNumber = product.getNumber() - checkGoods.getNumber();
			if (remainNumber < 0) {
				throw new RuntimeException("下单的商品货品数量大于库存量");
			}
			if (productService.reduceStock(productId, checkGoods.getNumber()) == 0) {
				throw new RuntimeException("商品货品库存减少失败");
			}
		}
		// 如果使用了优惠券，设置优惠券使用状态
		if (couponId != 0 && couponId != -1) {
			LitemallCouponUser couponUser = couponUserService.queryOne(userId, couponId);
			couponUser.setStatus(CouponUserConstant.STATUS_USED);
			couponUser.setUsedTime(LocalDateTime.now());
			couponUser.setOrderId(orderId);
			couponUserService.update(couponUser);
		}
		// 如果是团购项目，添加团购信息
		if (grouponRulesId != null && grouponRulesId > 0) {
			LitemallGroupon groupon = new LitemallGroupon();
			groupon.setOrderId(orderId);
			groupon.setPayed(false);
			groupon.setUserId(userId);
			groupon.setRulesId(grouponRulesId);
			// 参与者
			if (grouponLinkId != null && grouponLinkId > 0) {
				// 参与的团购记录
				LitemallGroupon baseGroupon = grouponService.queryById(grouponLinkId);
				groupon.setCreatorUserId(baseGroupon.getCreatorUserId());
				groupon.setGrouponId(grouponLinkId);
				groupon.setShareUrl(baseGroupon.getShareUrl());
			} else {
				groupon.setCreatorUserId(userId);
				groupon.setGrouponId(0);
			}
			grouponService.createGroupon(groupon);
		}
		Map<String, Object> data = new HashMap<>();
		data.put("orderId", orderId);
		return ResponseUtil.ok(data);
	}

	/**
	 * 取消订单
	 * <p>
	 * 1. 检测当前订单是否能够取消；
	 * 2. 设置订单取消状态；
	 * 3. 商品货品库存恢复；
	 * 4. 优惠券；
	 * 5. 团购活动。
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ orderId：xxx }
	 * @return 取消订单操作结果
	 */
	@Transactional
	public Object cancel(Integer userId, String body) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}
		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgumentValue();
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.badArgumentValue();
		}
		// 检测是否能够取消
		OrderHandleOption handleOption = OrderUtil.build(order);
		if (!handleOption.isCancel()) {
			return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能取消");
		}
		// 设置订单已取消状态
		order.setOrderStatus(OrderUtil.STATUS_CANCEL);
		order.setEndTime(LocalDateTime.now());
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			throw new RuntimeException("更新数据已失效");
		}
		// 商品货品数量增加
		List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
		for (LitemallOrderGoods orderGoods : orderGoodsList) {
		    Integer productId = orderGoods.getProductId();
		    Short number = orderGoods.getNumber();
			if (productService.addStock(productId, number) == 0) {
				throw new RuntimeException("商品货品库存增加失败");
			}
		}
	    return ResponseUtil.ok();
	}

	/**
	 * 付款订单的预支付会话标识
	 * <p>
	 * 1. 检测当前订单是否能够付款
	 * 2. 微信商户平台返回支付订单ID
	 * 3. 设置订单付款状态
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ orderId：xxx }
	 * @return 支付订单ID
	 */
	@Transactional
	public Object prepay(Integer userId, String body, HttpServletRequest request) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}
		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgumentValue();
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.badArgumentValue();
		}
		// 检测是否能够取消
		OrderHandleOption handleOption = OrderUtil.build(order);
		if (!handleOption.isPay()) {
			return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能支付");
		}
		LitemallUser user = userService.findById(userId);
		String openid = user.getWeixinOpenid();
		if (openid == null) {
			return ResponseUtil.fail(AUTH_OPENID_UNACCESS, "订单不能支付");
		}
		WxPayMpOrderResult result = null;
		try {
			WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
			orderRequest.setOutTradeNo(order.getOrderSn());
			orderRequest.setOpenid(openid);
			orderRequest.setBody("订单：" + order.getOrderSn());
			// 元转成分
//			int fee = 0;
//			BigDecimal actualPrice = order.getActualPrice();
//			fee = actualPrice.multiply(new BigDecimal(100)).intValue();
//			orderRequest.setTotalFee(fee);
			orderRequest.setTotalFee(1);
			orderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request));
			result = wxPayService.createOrder(orderRequest);
			// 缓存prepayID用于后续模版通知
			String prepayId = result.getPackageValue();
			prepayId = prepayId.replace("prepay_id=", "");
			LitemallUserFormid userFormid = new LitemallUserFormid();
			userFormid.setOpenid(user.getWeixinOpenid());
			userFormid.setFormid(prepayId);
			userFormid.setIsprepay(true);
			userFormid.setUseamount(3);
			userFormid.setExpireTime(LocalDateTime.now().plusDays(7));
			formIdService.addUserFormid(userFormid);
		} catch (Exception e) {
			e.printStackTrace();
			return ResponseUtil.fail(ORDER_PAY_FAIL, "订单不能支付");
		}
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			return ResponseUtil.updatedDateExpired();
		}
		return ResponseUtil.ok(result);
	}

	/**
	 * 微信付款成功或失败回调接口
	 * <p>
	 * 1. 检测当前订单是否是付款状态;
	 * 2. 设置订单付款成功状态相关信息;
	 * 3. 响应微信商户平台.
	 *
	 * @param request  请求内容
	 * @param response 响应内容
	 * @return 操作结果
	 */
	@Transactional
	public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
		String xmlResult = null;
		try {
			xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
			logger.info("xmlResult :: " + xmlResult);
		} catch (IOException e) {
			e.printStackTrace();
			return WxPayNotifyResponse.fail(e.getMessage());
		}

//		WxPayOrderNotifyResult result = null;
//		try {
//			result = wxPayService.parseOrderNotifyResult(xmlResult);
//			if (!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())) {
//				logger.error(xmlResult);
//				throw new WxPayException("微信通知支付失败！");
//			}
//			if (!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())) {
//				logger.error(xmlResult);
//				throw new WxPayException("微信通知支付失败！");
//			}
//		} catch (WxPayException e) {
//			e.printStackTrace();
//			return WxPayNotifyResponse.fail(e.getMessage());
//		}

		Document doc = null;
		Element root = null;
		try {
			doc = DocumentHelper.parseText(xmlResult);
			root = doc.getRootElement();
			Element elemResultCode = root.element("result_code");
			String resultCode = elemResultCode.getText();
			if (!WxPayConstants.ResultCode.SUCCESS.equals(resultCode)) {
				throw new WxPayException("微信通知支付失败！");
			}
			Element elemReturnCode = root.element("return_code");
			String returnCode = elemReturnCode.getText();
			if (!WxPayConstants.ResultCode.SUCCESS.equals(returnCode)) {
				throw new WxPayException("微信通知支付失败！");
			}
		} catch (WxPayException | DocumentException e) {
			e.printStackTrace();
			return WxPayNotifyResponse.fail(e.getMessage());
		}

		logger.info("处理腾讯支付平台的订单支付");
		Element elemOutTradeNo = root.element("out_trade_no");
		String orderSn = elemOutTradeNo.getText();
		Element elemTransactionId = root.element("transaction_id");
		String payId = elemTransactionId.getText();
		// 分转化成元
//		Element elemTotalFee = root.element("total_fee");
//		String totalFee = BaseWxPayResult.fenToYuan(Integer.valueOf(elemTotalFee.getText()));
		LitemallOrder order = orderService.findBySn(orderSn);
		if (order == null) {
			return WxPayNotifyResponse.fail("订单不存在 sn=" + orderSn);
		}
		// 检查这个订单是否已经处理过
		if (OrderUtil.isPayStatus(order) && order.getPayId() != null) {
			return WxPayNotifyResponse.success("订单已经处理成功!");
		}
		// 检查支付订单金额
//		if (!totalFee.equals(order.getActualPrice().toString())) {
//			return WxPayNotifyResponse.fail(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee);
//		}
		order.setPayId(payId);
		order.setPayTime(LocalDateTime.now());
		order.setOrderStatus(OrderUtil.STATUS_PAY);
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			// 这里可能存在这样一个问题，用户支付和系统自动取消订单发生在同时
			// 如果数据库首先因为系统自动取消订单而更新了订单状态；
			// 此时用户支付完成回调这里也要更新数据库，而由于乐观锁机制这里的更新会失败
			// 因此，这里会重新读取数据库检查状态是否是订单自动取消，如果是则更新成支付状态。
			order = orderService.findBySn(orderSn);
			int updated = 0;
			if (OrderUtil.isAutoCancelStatus(order)) {
				order.setPayId(payId);
				order.setPayTime(LocalDateTime.now());
				order.setOrderStatus(OrderUtil.STATUS_PAY);
				updated = orderService.updateWithOptimisticLocker(order);
			}
			// 如果updated是0，那么数据库更新失败
			if (updated == 0) {
				return WxPayNotifyResponse.fail("更新数据已失效");
			}
		}
		// 支付成功，有团购信息，更新团购信息
		LitemallGroupon groupon = grouponService.queryByOrderId(order.getId());
		if (groupon != null) {
			LitemallGrouponRules grouponRules = grouponRulesService.queryById(groupon.getRulesId());
			// 仅当发起者才创建分享图片
			if (groupon.getGrouponId() == 0) {
				String url = qCodeService.createGrouponShareImage(grouponRules.getGoodsName(), grouponRules.getPicUrl(),
					groupon);
				groupon.setShareUrl(url);
			}
			groupon.setPayed(true);
			if (grouponService.updateById(groupon) == 0) {
				return WxPayNotifyResponse.fail("更新数据已失效");
			}
		}

//		// 发送邮件和短信通知，这里采用异步发送
//		// 订单支付成功以后，会发送短信给用户，以及发送邮件给管理员
//		notifyService.notifyMail("新订单通知", order.toString());
//		// 这里微信的短信平台对参数长度有限制，所以将订单号只截取后6位
//		notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED,
//			new String[] { orderSn.substring(8, 14) });
//		// 请依据自己的模版消息配置更改参数
//		String[] parms = new String[] {
//			order.getOrderSn(),
//			order.getOrderPrice().toString(),
//			DateTimeUtil.getDateTimeDisplayString(order.getAddTime()),
//			order.getConsignee(),
//			order.getMobile(),
//			order.getAddress()
//		};
//		notifyService.notifyWxTemplate(result.getOpenid(), NotifyType.PAY_SUCCEED, parms,
//			"pages/index/index?orderId=" + order.getId());

		return WxPayNotifyResponse.success("处理成功!");
	}

    /**
     * 订单申请退款
     * <p>
     * 1. 检测当前订单是否能够退款；
     * 2. 设置订单申请退款状态。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单退款操作结果
     */
    public Object refund(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgument();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        OrderHandleOption handleOption = OrderUtil.build(order);
        if (!handleOption.isRefund()) {
            return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能取消");
        }

        // 设置订单申请退款状态
        order.setOrderStatus(OrderUtil.STATUS_REFUND);
        if (orderService.updateWithOptimisticLocker(order) == 0) {
            return ResponseUtil.updatedDateExpired();
        }

        // 发送邮件和短信通知，这里采用异步发送
        // 有用户申请退款，邮件通知运营人员
        notifyService.notifyMail("退款申请", order.toString());

        return ResponseUtil.ok();
    }

    /**
     * 确认收货
     * <p>
     * 1. 检测当前订单是否能够确认收货；
     * 2. 设置订单确认收货状态。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    public Object confirm(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgument();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        OrderHandleOption handleOption = OrderUtil.build(order);
        if (!handleOption.isConfirm()) {
            return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能确认收货");
        }

        Short comments = orderGoodsService.getComments(orderId);
        order.setComments(comments);

        order.setOrderStatus(OrderUtil.STATUS_CONFIRM);
        order.setConfirmTime(LocalDateTime.now());
        if (orderService.updateWithOptimisticLocker(order) == 0) {
            return ResponseUtil.updatedDateExpired();
        }
        return ResponseUtil.ok();
    }

    /**
     * 删除订单
     * <p>
     * 1. 检测当前订单是否可以删除；
     * 2. 删除订单。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    public Object delete(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgument();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        OrderHandleOption handleOption = OrderUtil.build(order);
        if (!handleOption.isDelete()) {
            return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能删除");
        }

        // 订单order_status没有字段用于标识删除
        // 而是存在专门的delete字段表示是否删除
        orderService.deleteById(orderId);

        return ResponseUtil.ok();
    }

    /**
     * 待评价订单商品信息
     *
     * @param userId  用户ID
     * @param orderId 订单ID
     * @param goodsId 商品ID
     * @return 待评价订单商品信息
     */
    public Object goods(Integer userId, Integer orderId, Integer goodsId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        List<LitemallOrderGoods> orderGoodsList = orderGoodsService.findByOidAndGid(orderId, goodsId);
        int size = orderGoodsList.size();

        Assert.state(size < 2, "存在多个符合条件的订单商品");

        if (size == 0) {
            return ResponseUtil.badArgumentValue();
        }

        LitemallOrderGoods orderGoods = orderGoodsList.get(0);
        return ResponseUtil.ok(orderGoods);
    }

    /**
     * 评价订单商品
     * <p>
     * 确认商品收货或者系统自动确认商品收货后7天内可以评价，过期不能评价。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    public Object comment(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        Integer orderGoodsId = JacksonUtil.parseInteger(body, "orderGoodsId");
        if (orderGoodsId == null) {
            return ResponseUtil.badArgument();
        }
        LitemallOrderGoods orderGoods = orderGoodsService.findById(orderGoodsId);
        if (orderGoods == null) {
            return ResponseUtil.badArgumentValue();
        }
        Integer orderId = orderGoods.getOrderId();
        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgumentValue();
        }
        if (!OrderUtil.isConfirmStatus(order) && !OrderUtil.isAutoConfirmStatus(order)) {
            return ResponseUtil.fail(ORDER_INVALID_OPERATION, "当前商品不能评价");
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.fail(ORDER_INVALID, "当前商品不属于用户");
        }
        Integer commentId = orderGoods.getComment();
        if (commentId == -1) {
            return ResponseUtil.fail(ORDER_COMMENT_EXPIRED, "当前商品评价时间已经过期");
        }
        if (commentId != 0) {
            return ResponseUtil.fail(ORDER_COMMENTED, "订单商品已评价");
        }

        String content = JacksonUtil.parseString(body, "content");
        Integer star = JacksonUtil.parseInteger(body, "star");
        if (star == null || star < 0 || star > 5) {
            return ResponseUtil.badArgumentValue();
        }
        Boolean hasPicture = JacksonUtil.parseBoolean(body, "hasPicture");
        List<String> picUrls = JacksonUtil.parseStringList(body, "picUrls");
        if (hasPicture == null || !hasPicture) {
            picUrls = new ArrayList<>(0);
        }

        // 1. 创建评价
        LitemallComment comment = new LitemallComment();
        comment.setUserId(userId);
        comment.setType((byte) 0);
        comment.setValueId(orderGoods.getGoodsId());
        comment.setStar(star.shortValue());
        comment.setContent(content);
        comment.setHasPicture(hasPicture);
        comment.setPicUrls(picUrls.toArray(new String[]{}));
        commentService.save(comment);

        // 2. 更新订单商品的评价列表
        orderGoods.setComment(comment.getId());
        orderGoodsService.updateById(orderGoods);

        // 3. 更新订单中未评价的订单商品可评价数量
        Short commentCount = order.getComments();
        if (commentCount > 0) {
            commentCount--;
        }
        order.setComments(commentCount);
        orderService.updateWithOptimisticLocker(order);

        return ResponseUtil.ok();
    }

	@Transactional
	public void payDummy(Integer orderId) {
		LitemallOrder order = orderService.findById(orderId);
		order.setPayId("666");
		order.setPayTime(LocalDateTime.now());
		order.setOrderStatus(OrderUtil.STATUS_PAY);
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			order = orderService.findById(orderId);
			int updated = 0;
			if (OrderUtil.isAutoCancelStatus(order)) {
				order.setPayId("666");
				order.setPayTime(LocalDateTime.now());
				order.setOrderStatus(OrderUtil.STATUS_PAY);
				updated = orderService.updateWithOptimisticLocker(order);
				System.out.println("updated=" + updated);
			}
		}
	}
}